﻿using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using QuickTuner.Properties;
using QuickTuner.Util;

namespace QuickTuner
{
    /// <summary>
    /// QuickTuner's isolated storage management
    /// </summary>
    public static class Storage
    {
        public const string RadioFilename = "radio.xml";

        #region Helpers

        // perform arbitrary file action wrapped in proper initialization and cleanup
        private static void FileAction(string filename, FileMode mode, Action<Stream> action)
        {
            var storage = IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream stream;


            // stream opens depends on mode
            switch (mode) {

                case FileMode.OpenOrCreate:
                case FileMode.Create:
                case FileMode.CreateNew:
                    stream = new IsolatedStorageFileStream(filename, mode, storage);
                    break;

                default:
                    // resolve filename pattern and also check for file existence
                    filename = storage.GetFileNames(filename).FirstOrDefault();

                    // set stream = null if file doesn't exists
                    stream = filename == null
                        ? null
                        : new IsolatedStorageFileStream(filename, mode, storage);

                    break;

            }

            // runs the supplied action on the stream
            try {
                action(stream);

                if (stream != null) stream.Close();
                storage.Close();

            } finally {
                if (stream != null) stream.Dispose();
                storage.Dispose();

            }

        }

        private static T FileAction<T>(string filename, FileMode mode, Func<Stream, T> action)
        {
            T returnVal = default(T);

            FileAction(filename, mode, delegate(Stream s) {
                returnVal = action(s);
            });

            return returnVal;
        }

        #endregion

        public static bool EnsureRadio()
        {

            var result = true;


            // a function to try and load the default templates
            // and if there are exceptions, EnsureRadio should returns false
            Action tryLoadDefault = () => {
                try { LoadDefaultTemplates(); } catch { result = false; }
            };


            // try to load the radio file
            FileAction(RadioFilename, FileMode.Open, s => {

                if (s == null) // no stream loaded, init defaults
                    tryLoadDefault();

                else // if any exceptions, we wipe clean and load defaults
                    try { var radio = Radio.LoadFrom(s); } catch { tryLoadDefault(); }

            });


            return result;

        }

        public static void LoadDefaultTemplates()
        {
            // delete all files and directories in the storage
            using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) {

                storage.GetDirectoryNames("*.*").ForEach(dir => storage.DeleteDirectory(dir));
                storage.GetFileNames("*.*").ForEach(file => storage.DeleteFile(file));

                storage.Close();

            }

            // load the default files from app's embedded resource

            // copy files from resource into the isolatedstorage
            FileAction(RadioFilename, FileMode.CreateNew,
                s => {
                    using (var sw = new StreamWriter(s)) {
                        sw.Write(Resources.radio_xml);
                        sw.Close();
                    }
                });

        }

        public static Radio LoadRadio()
        {
            if (!EnsureRadio()) return null;

            return FileAction(RadioFilename, FileMode.Open, s => Radio.LoadFrom(s));
        }

        public static void SaveRadio(Radio instance)
        {
            FileAction(RadioFilename, FileMode.Truncate,
                s => instance.SaveTo(s));
        }
    }
}
